#include <gtk/gtk.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <unistd.h>
#include <stdbool.h>

// 游戏核心配置
#define INIT_WIDTH  25     // 初始地图宽度（格子数）
#define INIT_HEIGHT 25    // 初始地图高度（格子数）
#define CELL_SIZE  30     // 每个格子像素大小
#define INIT_SPEED 250    // 初始移动间隔（毫秒），数值越小速度越快
#define MAX_OBSTACLES 100 //最大障碍物数
#define MAX_TAIL 600//蛇的最大长度
// 蛇移动方向枚举
typedef enum { UP, DOWN, LEFT, RIGHT } Direction;

// 蛇节点结构体（链表实现）
typedef struct SnakeNode {
    int x, y;
    struct SnakeNode *next;
} SnakeNode;

// 游戏状态结构体
typedef struct {
    SnakeNode *snake_head; // 蛇头（链表头）
    int snake_len;         // 蛇长度
    int tail_x[MAX_TAIL],tail_y[MAX_TAIL];
    Direction dir;         // 当前移动方向

    int fruit_x, fruit_y;  // 食物位置

    int level;             // 当前关卡（从 1 开始）
    int score;             // 当前关卡得分
    gboolean running;      // 游戏是否在运行（暂停控制）
    gboolean game_over;    // 游戏是否结束

    // 关卡配置
    int map_width;
    int map_height;
    int speed;

    //障碍物信息
    int obstaclesX[MAX_OBSTACLES];
    int obstaclesY[MAX_OBSTACLES];
    int obstacleCount ;
} GameState;

// 全局变量（方便 GTK 回调访问）
GameState game;
GtkWidget *drawing_area;
GtkWidget *score_label;
GtkWidget *level_label;
GtkWidget *name_label;
GtkWidget *high_score_dialog; // 排行榜弹窗

// 初始化链表节点
SnakeNode* create_snake_node(int x, int y) {
    SnakeNode *node = (SnakeNode*)malloc(sizeof(SnakeNode));
    node->x = x;
    node->y = y;
    node->next = NULL;
    return node;
}

// 释放蛇链表内存
void free_snake() {
    SnakeNode *curr = game.snake_head;
    while (curr != NULL) {
        SnakeNode *temp = curr;
        curr = curr->next;
        free(temp);
    }
    game.snake_head = NULL;
}

// 初始化游戏状态（含蛇、食物、关卡等）
void init_game() {
    srand(time(NULL));
    free_snake(); // 确保释放旧蛇

    // 初始化蛇（链表实现，初始 3 节）
    game.snake_head = create_snake_node(INIT_WIDTH/2, INIT_HEIGHT/2);
    game.snake_head->next = create_snake_node(INIT_WIDTH/2, INIT_HEIGHT/2 + 1);
    game.snake_head->next->next = create_snake_node(INIT_WIDTH/2, INIT_HEIGHT/2 + 2);
    game.snake_len = 3;
    game.dir = UP;

    // 关卡配置初始化
    game.level = 1;
    game.map_width = INIT_WIDTH;
    game.map_height = INIT_HEIGHT;
    game.speed = INIT_SPEED;
    game.score = 0;

    // 初始化食物
    game.fruit_x = rand() % game.map_width;
    game.fruit_y = rand() % game.map_height;

    game.running = TRUE;
    game.game_over = FALSE;
}
void generateObstacles();//障碍物函数声明
// 生成食物（确保不与蛇身重叠）
void spawn_fruit() {
    gboolean valid;
    do {
        valid = TRUE;
        game.fruit_x = rand() % game.map_width;
        game.fruit_y = rand() % game.map_height;

        // 检查食物是否与蛇身重叠
        SnakeNode *curr = game.snake_head;
        while (curr != NULL) {
            if (curr->x == game.fruit_x && curr->y == game.fruit_y) {
                valid = FALSE;
                break;
            }
            curr = curr->next;
        }
    } while (!valid);
}

// GTK 绘制回调：负责绘制蛇、食物、边界
gboolean on_draw_event(GtkWidget *widget, cairo_t *cr, gpointer user_data) {
    // 绘制背景（黑色）
    cairo_set_source_rgb(cr, 0, 0, 0);
    cairo_rectangle(cr, 0, 0, game.map_width * CELL_SIZE, game.map_height * CELL_SIZE);
    cairo_fill(cr);

    if (game.game_over) {
        // 游戏结束提示文字
        cairo_set_source_rgb(cr, 1, 0, 0);
        cairo_select_font_face(cr, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
        cairo_set_font_size(cr, 40);
        cairo_move_to(cr, (game.map_width * CELL_SIZE - 200) / 2, (game.map_height * CELL_SIZE) / 2);
        cairo_show_text(cr, "GAME OVER");
        return FALSE;
    }

    // 绘制蛇身（绿色）
    cairo_set_source_rgb(cr, 0, 1, 1);
    SnakeNode *curr = game.snake_head;
    while (curr != NULL) {
        cairo_rectangle(cr,
                        curr->x * CELL_SIZE,
                        curr->y * CELL_SIZE,
                        CELL_SIZE, CELL_SIZE);
        cairo_fill(cr);
        curr = curr->next;
    }

    // 绘制食物（红色）
    cairo_set_source_rgb(cr, 1, 0, 1);
    cairo_rectangle(cr,
                    game.fruit_x * CELL_SIZE,
                    game.fruit_y * CELL_SIZE,
                    CELL_SIZE, CELL_SIZE);
    cairo_fill(cr);

    // 绘制地图边界（白色）
    cairo_set_source_rgb(cr, 1, 1, 1);
    cairo_rectangle(cr, 0, 0, game.map_width * CELL_SIZE, game.map_height * CELL_SIZE);
    cairo_stroke(cr);

    // 绘制障碍物
    cairo_set_source_rgb(cr, 0.5, 0, 0.5); // 紫色
    for (int i = 0; i < game.obstacleCount; i++) {
        cairo_rectangle(cr, game.obstaclesX[i] * CELL_SIZE + 2, game.obstaclesY[i] * CELL_SIZE + 2,
                       CELL_SIZE - 4, CELL_SIZE - 4);
        cairo_fill(cr);
    }

    return FALSE;
}

// 检查碰撞：撞墙、撞自己
gboolean check_collision() {
    SnakeNode *head = game.snake_head;
    // 撞墙检测
    if (head->x < 0 || head->x >= game.map_width ||
        head->y < 0 || head->y >= game.map_height) {
        return TRUE;
    }

    // 撞自己检测（蛇头碰身体）
    SnakeNode *curr = head->next;
    while (curr != NULL) {
        if (head->x == curr->x && head->y == curr->y) {
            return TRUE;
        }
        curr = curr->next;
    }
    return FALSE;
}

// 文件 IO：保存得分到排行榜（简单文本文件实现）
void save_high_score(int score) {
    FILE *file = fopen("high_scores.txt", "a");
    if (file != NULL) {
        fprintf(file, "%d\n", score);
        fclose(file);
    }
}

// 文件 IO：读取排行榜并排序  //可改为SQlite数据库读取用户信息
void load_high_scores(int scores[], int max_size) {
    FILE *file = fopen("high_scores.txt", "r");
    if (file == NULL) return;

    int i = 0;
    while (fscanf(file, "%d", &scores[i]) == 1 && i < max_size) {
        i++;
    }
    fclose(file);

    // 简单冒泡排序
    for (int j = 0; j < i-1; j++) {
        for (int k = 0; k < i-j-1; k++) {
            if (scores[k] < scores[k+1]) {
                int temp = scores[k];
                scores[k] = scores[k+1];
                scores[k+1] = temp;
            }
        }
    }
}

// 显示排行榜弹窗
void show_high_scores(GtkWidget *parent) {
    if (high_score_dialog) {
        gtk_window_present(GTK_WINDOW(high_score_dialog));
        return;
    }

    int scores[100] = {0}; // 最多保存 100 条记录
    load_high_scores(scores, 100);

    high_score_dialog = gtk_dialog_new_with_buttons("排行榜",
                                                    GTK_WINDOW(parent),
                                                    GTK_DIALOG_MODAL,
                                                    "关闭", GTK_RESPONSE_CLOSE,
                                                    NULL);
    GtkWidget *content_area = gtk_dialog_get_content_area(GTK_DIALOG(high_score_dialog));
    GtkWidget *label = gtk_label_new("Top 10 得分：");
    gtk_container_add(GTK_CONTAINER(content_area), label);

    char text[256] = "Top 10 得分：\n";
    for (int i = 0; i < 10 && scores[i] > 0; i++) {
        char line[32];
        sprintf(line, "%d: %d\n", i+1, scores[i]);
        strcat(text, line);
    }
    gtk_label_set_text(GTK_LABEL(label), text);

    gtk_widget_show_all(high_score_dialog);
}

// 游戏更新逻辑（定时器回调）
gboolean update_game(gpointer user_data) {//动态游戏状态
    if (!game.running || game.game_over) {
       // return TRUE; // 暂停或结束时不更新
        return G_SOURCE_CONTINUE; // 暂停或结束时不更新，但保持定时器运行
    }

    // 移动蛇：新建蛇头，链表后移
    SnakeNode *new_head = create_snake_node(game.snake_head->x, game.snake_head->y);
    switch (game.dir) {
        case UP:    new_head->y--; break;
        case DOWN:  new_head->y++; break;
        case LEFT:  new_head->x--; break;
        case RIGHT: new_head->x++; break;
    }
    new_head->next = game.snake_head;
    game.snake_head = new_head;

    // 检查是否吃到食物
    if (game.snake_head->x == game.fruit_x && game.snake_head->y == game.fruit_y) {
        game.snake_len++;
        game.score += 10 * game.level;
        spawn_fruit();

        // 关卡升级逻辑：得分达 100*当前关卡则升级
        if (game.score >= 100 * game.level) {
            game.level++;
            // 关卡升级：加速、扩大地图
            game.speed -= 20; // 速度加快
           /* game.map_width += 2;
            game.map_height += 2;*/
            gchar *level_text = g_strdup_printf("Level: %d", game.level);
            gtk_label_set_text(GTK_LABEL(level_label), level_text);
            g_free(level_text);

            // 重新初始化食物（适应新地图）
            spawn_fruit();
            //添加障碍物函数
            generateObstacles(&game);
        }
    } else {
        // 没吃到食物，删除尾部节点
        SnakeNode *curr = game.snake_head;
        while (curr->next->next != NULL) {
            curr = curr->next;
        }
        free(curr->next);
        curr->next = NULL;
    }

    // 检查碰撞（游戏结束判断）
    if (check_collision()) {
        game.game_over = TRUE;
        game.running = FALSE;

        // 得分存入文件
        save_high_score(game.score);
        // 显示排行榜
        show_high_scores(gtk_widget_get_toplevel(drawing_area));
    }

    // 更新得分显示
    gchar *score_text = g_strdup_printf("Score: %d", game.score);
    gtk_label_set_text(GTK_LABEL(score_label), score_text);
    g_free(score_text);

    // 触发重绘
    gtk_widget_queue_draw(drawing_area);

    // 动态调整定时器速度（关卡加速）
    //return TRUE;

// 原有游戏逻辑
return G_SOURCE_CONTINUE;

}

// 键盘事件回调：控制方向、暂停
gboolean on_key_press(GtkWidget *widget, GdkEventKey *event, gpointer user_data) {
    switch (event->keyval) {
        case GDK_KEY_Up:    if (game.dir != DOWN)  game.dir = UP;    break;
        case GDK_KEY_Down:  if (game.dir != UP)    game.dir = DOWN;  break;
        case GDK_KEY_Left:  if (game.dir != RIGHT) game.dir = LEFT;  break;
        case GDK_KEY_Right: if (game.dir != LEFT)  game.dir = RIGHT; break;
        case GDK_KEY_p:     game.running = !game.running; break; // P 键暂停/继续
        default: break;
    }
    return TRUE;
}

// 检查位置是否可放置障碍物
bool checkObstaclePosition(GameState *game, int x, int y) {
    // 检查是否超出边界 (边界不生成障碍物，边界单独处理)
    if (x < 0 || x >= INIT_WIDTH || y < 0 || y >= INIT_HEIGHT) {
        return false;
    }

    // 检查是否与蛇身重叠
    for (int i = 0; i < game->snake_len; i++) {
        if (x == game->tail_x[i] && y == game->tail_y[i]) {
            return false;
        }
    }

    // 检查是否与食物重叠
    if (x == game-> fruit_x&& y == game->fruit_y) {
        return false;
    }

    // 检查是否与已有障碍物重叠
    for (int i = 0; i < game->obstacleCount; i++) {
        if (x == game->obstaclesX[i] && y == game->obstaclesY[i]) {
            return false;
        }
    }

    return true;
}

    // 生成障碍物（根据关卡动态调整数量和难度）
    void generateObstacles(GameState *game) {
    game->obstacleCount = 0;

    // 关卡1：障碍物少，速度慢
    if (game->level == 1) {
        game->obstacleCount = 5;  // 少量障碍物

    }
    // 关卡2：障碍物比初级多，速度增加
    else if (game->level == 2) {
        game->obstacleCount = 15; // 中等数量障碍物
    }
    // 关卡3：障碍物比中级多，速度增加
    else if (game->level == 3) {
        game->obstacleCount = 30; // 大量障碍物
    }

    // 生成障碍物
    for (int i = 0; i < game->obstacleCount; i++) {
        int x, y;
        bool validPosition;

        do {
            x = rand() % INIT_WIDTH;
            y = rand() % INIT_HEIGHT;
            validPosition = checkObstaclePosition(game, x, y);
        } while (!validPosition);

        game->obstaclesX[i] = x;
        game->obstaclesY[i] = y;
    }
}
// 开始游戏按钮处理
void on_start_click(GtkWidget *btn, gpointer data) {
    game.running = TRUE;
    game.game_over = FALSE;
    init_game(); // 重新初始化游戏
    g_print("游戏已开始\n");
}

// 暂停游戏按钮处理
void on_pause_click(GtkWidget *btn, gpointer data) {
    game.running = !game.running;
    if (game.running) {
        gtk_button_set_label(GTK_BUTTON(btn), "暂停游戏");
        g_print("游戏继续\n");
    } else {
        gtk_button_set_label(GTK_BUTTON(btn), "继续游戏");
        g_print("游戏暂停\n");
    }
}
// 重新开始游戏按钮处理
void on_restart_click(GtkWidget *btn, gpointer data) {
    // 重置游戏状态
    game.running = TRUE;
    game.game_over = FALSE;
    game.score = 0;
    game.level = 1;
    game.speed = INIT_SPEED; // 恢复初始速度

    // 重新初始化蛇、食物、障碍物
    init_game();

    // 重置界面显示
    gchar *score_text = g_strdup_printf("Score: %d", game.score);
    gtk_label_set_text(GTK_LABEL(score_label), score_text);
    g_free(score_text);

    gchar *level_text = g_strdup_printf("Level: %d", game.level);
    gtk_label_set_text(GTK_LABEL(level_label), level_text);
    g_free(level_text);

    gtk_button_set_label(GTK_BUTTON(btn), "重新开始"); // 恢复按钮文字
    g_print("游戏已重新开始\n");
}

int main(int argc, char *argv[]){
    // 初始化 GTK
    gtk_init(&argc, &argv);

    // 创建主窗口
    GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(window), "贪吃蛇（多关卡版）");

    // 窗口大小：地图尺寸 + 信息栏高度
    gtk_window_set_default_size(GTK_WINDOW(window),
                               INIT_WIDTH * CELL_SIZE,
                               INIT_HEIGHT * CELL_SIZE + 100);
    g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);

    /*// 1. 外层的上下结构的容器 container
    //      2. 将 container 加入到 window
    GtkWidget *container = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
    gtk_container_add(GTK_CONTAINER(window), container);

    //      3. 创建标题label   label_title
    //      4. 放置label_title到container的最上方
    name_label = gtk_label_new("SNAKE");
    gtk_box_pack_start(container, name_label,FALSE,FALSE, 0);*/



    // 垂直布局容器：游戏区 + 信息栏
    GtkWidget *vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
    gtk_container_add(GTK_CONTAINER(window), vbox);


    // 游戏绘制区域
    drawing_area = gtk_drawing_area_new();
    gtk_box_pack_start(GTK_BOX(vbox), drawing_area, TRUE, TRUE, 0);
    g_signal_connect(G_OBJECT(drawing_area), "draw", G_CALLBACK(on_draw_event), NULL);
    g_signal_connect(G_OBJECT(drawing_area), "key-press-event", G_CALLBACK(on_key_press), NULL);
    gtk_widget_set_can_focus(drawing_area, TRUE); // 允许聚焦以接收键盘事件
    gtk_widget_grab_focus(drawing_area);          // 默认聚焦

    // 信息栏：得分 + 关卡
    GtkWidget *hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 20);
    gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 10);

    score_label = gtk_label_new("Score: 0");
    level_label = gtk_label_new("Level: 1");
    gtk_box_pack_start(GTK_BOX(hbox), score_label, TRUE, TRUE, 0);
    gtk_box_pack_start(GTK_BOX(hbox), level_label, TRUE, TRUE, 0);

    // **添加按钮区域**
    GtkWidget *button_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 10);
    gtk_box_pack_start(GTK_BOX(vbox), button_box, FALSE, FALSE, 10);

    // 开始按钮
    GtkWidget *start_btn = gtk_button_new_with_label("开始游戏");
    g_signal_connect(start_btn, "clicked", G_CALLBACK(on_start_click), NULL);
    gtk_box_pack_start(GTK_BOX(button_box), start_btn, FALSE, FALSE, 0);

    // 暂停按钮
    GtkWidget *pause_btn = gtk_button_new_with_label("暂停游戏");
    g_signal_connect(pause_btn, "clicked", G_CALLBACK(on_pause_click), NULL);
    gtk_box_pack_start(GTK_BOX(button_box), pause_btn, FALSE, FALSE, 0);

    GtkWidget *restart_btn = gtk_button_new_with_label("重新开始");
    g_signal_connect(restart_btn, "clicked", G_CALLBACK(on_restart_click), NULL);
    gtk_box_pack_start(GTK_BOX(button_box), restart_btn, FALSE, FALSE, 0);

    // 初始化游戏状态
    init_game();

    // 启动游戏定时器（控制蛇移动速度）
    g_timeout_add(game.speed, update_game, NULL);

    // 显示窗口
    gtk_widget_show_all(window);
    // 进入 GTK 主循环
    gtk_main();

    // 释放资源
    free_snake();

    return 0;
}